import "./SetMars3dMap.scss"
import * as mars3d from "mars3d"
import { v4 } from 'uuid'
import { useEffect, useState } from "react";
import { useEventEmitter, useReactive } from "ahooks"
import { Tabs, Popover, Input, Button, Tree, Dropdown, Tooltip, App, Drawer, Popconfirm } from "antd"
import {
    BuildOutlined,
    NodeIndexOutlined,
    EnvironmentOutlined,
    DownOutlined,
    DeleteOutlined,
    EditOutlined,
    EyeOutlined,
    EyeInvisibleOutlined
} from '@ant-design/icons'
import { onTreeDrop, replaceNodeById, removeTreeByKey, updateTreeByKey } from "../../Utils"
import { FormTempMapping } from '../../Utils/FormTemp'
import { Marsd3dConfig } from '../../Config/Mars3dConfig'
import { modelStore } from '../../Config/zustand'
import { LayerListMap, BoundaryBorderFunction } from '../../Utils/Mars3dConfig'
import { MappingData } from '../../Config/MappingData'
import { initStartDraw } from '../../Utils/Mars3dParams'

// DIV元素
const divType = ['div', 'divPlane']
// 单点元素
const singlePoint = [
    'modelP', 'pointP', 'labelP', 'billboardP', 'billboardIndicator', 'tetrahedron', 'div', 'divPlane', 'divLightPoint', 'divUpLabel', 'divBoderLabel',
    'boxP', 'cylinderP', 'lightCone', 'ellipsoidP', 'circleP', 'pointLight'
]

const singlePoints = ['regular', 'sector']

const SetMars3dMap = ({ data }) => {
    const { updateModel } = modelStore()
    const { message, modal, notification } = App.useApp()
    const { type, config, MapEvent, map, gra, clip } = data

    if (type === 'A01') {
        const [Active, setActive] = useState('scene')
        const itemMapping = {
            scene: { label: '基础设置', formItem: Marsd3dConfig.SceneBaseConfig },
            globe: { label: '地球设置', formItem: Marsd3dConfig.SceneGlobeConfig },
            cameraController: { label: '操作设置', formItem: Marsd3dConfig.SceneCameraController },
            other: { label: '工具瓦片', formItem: Marsd3dConfig.SceneTerrainConfig },
            weather: { label: '天气设置', formItem: Marsd3dConfig.SceneWeatherConfig },
            colour: { label: '色彩设置', formItem: Marsd3dConfig.SceneColourConfig }
        }
        const onSave = (data) => {
            if (Active) {
                config[Active] = data
                if (Active === 'scene') Object.keys(data).forEach(key => map.setSceneOptions({ [key]: data[key] }))
                if (Active === 'globe') Object.keys(data).forEach(key => map.setSceneOptions({ globe: { [key]: data[key] } }))
                if (Active === 'cameraController') Object.keys(data).forEach(key => map.setSceneOptions({ cameraController: { [key]: data[key] } }))
                if (Active === 'other') {
                    Object.keys(data).forEach(key => {
                        if (key === 'show') map.hasTerrain = data[key]
                        if (key === 'wireframe') map.scene.globe._surface.tileProvider._debug.wireframe = data[key]
                        if (key === 'basemap') map.basemap = data[key]
                        if (key === 'layer') map.setLayersOptions(LayerListMap(data[key]))
                        if (key === 'toolbar') map.control.toolbar.show = data[key]
                        if (key === 'toolbar_position') map.control.toolbar.setOptions({ position: data[key] })
                        if (key === 'geocoder') map.control.geocoder.show = data[key]
                        if (key === 'homeButton') map.control.homeButton.show = data[key]
                        if (key === 'locationBar') map.control.locationBar.show = data[key]
                        if (key === 'distanceLegend') map.control.distanceLegend.show = data[key]
                    })
                }
                if (Active === 'weather') {
                    Object.keys(data).forEach(key => {
                        const [lot, field] = key.split('_')
                        map.effects[lot][field] = data[key]
                    })
                }
                if (Active === 'colour') {
                    Object.keys(data).forEach(key => {
                        const [lot, field] = key.split('_')
                        map.effect[lot][field] = data[key]
                    })
                }
                MapEvent.emit({ type: 'onSaveConfig', data: config })
            }
        }
        const CallBackFunc = (e) => {
            const { type, data } = e
            const MapReturn = new Map([
                ['onFormBack', () => onSave(data)],
            ])
            const func = MapReturn.get(type)
            return func && func()
        }
        const FORMEVENT = useEventEmitter()
        FORMEVENT.useSubscription(CallBackFunc)

        const Itme = Object.keys(itemMapping).map(key => ({
            key,
            label: itemMapping[key].label,
            children: <FormTempMapping formItem={itemMapping[key].formItem} FORMEVENT={FORMEVENT} Initial={config[key]} NotLoading />
        }))
        return (
            <div className="SetMars3dMap SetMars3dMapA01">
                <Tabs value={Active} centered items={Itme} onChange={setActive} />
            </div>
        )
    }
    if (type === 'A02') {
        const [Active, setActive] = useState('border')
        const itemMapping = {
            border: { label: '剪裁区', formItem: Marsd3dConfig.BoundaryBorderConfig },
            cover: { label: '覆盖面', formItem: Marsd3dConfig.BoundaryCoverConfig },
            line: { label: '边界线', formItem: Marsd3dConfig.BoundaryLineConfig },
            wall: { label: '边界墙', formItem: Marsd3dConfig.BoundaryWallConfig },
        }

        const onSave = (data) => {
            if (Active) {
                config[Active] = data
                BoundaryBorderFunction(gra, clip, config)
                MapEvent.emit({ type: 'onSaveConfig', data: config })
            }
        }
        const CallBackFunc = (e) => {
            const { type, data } = e
            const MapReturn = new Map([
                ['onFormBack', () => onSave(data)],
            ])
            const func = MapReturn.get(type)
            return func && func()
        }
        const FORMEVENT = useEventEmitter()
        FORMEVENT.useSubscription(CallBackFunc)


        const Itme = Object.keys(itemMapping).map(key => ({
            key,
            label: itemMapping[key].label,
            children: <FormTempMapping formItem={itemMapping[key].formItem} FORMEVENT={FORMEVENT} Initial={config[key]} NotLoading />
        }))
        return (
            <div className="SetMars3dMap SetMars3dMapA02">
                <Tabs value={Active} centered items={Itme} onChange={setActive} />
            </div>
        )
    }
    if (type === 'A03') {
        const { list } = config.camera
        const [Open, setOpen] = useState(false)
        const [NewName, setNewName] = useState()
        const [Init, setInit] = useState(config.camera.default)

        const onLoading = (value) => {
            map.setCameraView(value)
        }
        const onDefault = (key) => {
            setInit(key)
            config.camera.default = key
            MapEvent.emit({ type: 'onSaveConfig', data: config })
        }
        const onSave = () => {
            config.camera.list[NewName] = map.getCameraView()
            setNewName()
            setOpen(false)
            MapEvent.emit({ type: 'onSaveConfig', data: config })
        }

        return (
            <div className="SetMars3dMap SetMars3dMapA03">
                <div className='List'>
                    {Object.entries(list).map(([key, value], index) => {
                        const { lng, lat, alt, heading, pitch } = value
                        return (
                            <div key={index} className='CameraCard' onClick={() => onLoading(value)}>
                                <div className='number'>
                                    <div> 经度值 : <span>{lng}</span> </div>
                                    <div> 纬度值 : <span>{lat}</span> </div>
                                    <div> 高度值 : <span>{alt}</span> </div>
                                    <div> 方向角 : <span>{heading}</span> </div>
                                    <div> 俯仰角 : <span>{pitch}</span> </div>
                                </div>
                                <div className='CameraBanner' />
                                <div className='CameraName'><span className={Init === key ? 'active' : ''}>{key}</span></div>
                                {Init !== key &&
                                    <div className='CameraOptions'>
                                        <Button type='link' onClick={() => onDefault(key)}>默认</Button>
                                        {/* <Button type='link' danger onClick={() => onDelete(key)}>删除</Button> */}
                                    </div>
                                }
                            </div>
                        )
                    })}
                </div>
                <div className="Button">
                    <Popover
                        content={
                            <div className='SetMars3dMapA03__Input' >
                                <Input value={NewName} onChange={e => setNewName(e.target.value)} />
                                <Button type='primary' onClick={onSave}>保存视角</Button>
                            </div>
                        }
                        title="视角名称"
                        trigger="click"
                        open={Open}
                        onOpenChange={setOpen}
                    >
                        <Button type='primary' block size='large' >添加视角</Button>
                    </Popover>
                </div>
            </div>
        )
    }
    if (type === 'A04') {
        gra.isAutoEditing = true
        const { elements } = config
        const [Open, setOpen] = useState(false)
        const [loading, setLoading] = useState(false)
        const [TreeData, setTreeData] = useState(elements)
        const [Activate, setActivate] = useState({})
        const onAdd = () => updateModel({ type: 'AddFormData', width: 640, title: '新增数据', data: { type: 'AddElement', AddEvnet: ElementEvent } })
        const onModify = e => updateModel({ type: 'AddFormData', width: 640, title: '修改数据', data: { type: 'AddElement', AddEvnet: ElementEvent, Initial: e } })
        const onUpdata = (data) => {
            const arr = data.uuid ? replaceNodeById(TreeData, data.uuid, data) : [...TreeData, { ...data, uuid: v4() }]
            console.log(data)
            console.log(arr)
            config.elements = arr
            setTreeData(arr)
            onSave()
            ElementEvent.emit({ type: 'closeForm' })
        }

        const CallBackFunc = (e) => {
            const { type, data } = e
            // console.log('ElementEventBack', e)
            const MapReturn = new Map([
                ['onFormBack', () => onUpdata(data)],
            ])
            const func = MapReturn.get(type)
            return func && func()
        }
        const ElementEvent = useEventEmitter()
        ElementEvent.useSubscription(CallBackFunc)

        const onDraw = async (e) => {
            const { uuid, elementType } = e
            const style = JSON.parse(JSON.stringify(initStartDraw[elementType]))
            if (divType.includes(elementType)) style.style.html = initStartDraw.DivTemplate[style.style.temp](style)
            const data = await gra.startDraw({ id: uuid, type: elementType, ...style })
            // console.log('绘制元素', data)
        }

        const onLocate = (e) => {
            const ELE = gra.getGraphicById(e.uuid)
            map.flyToGraphic(ELE)
        }
        const onDelete = (e) => {
            const ELE = gra.getGraphicById(e.uuid)
            if (ELE) {
                const arr = config.elementsData.filter(v => v.id !== ELE.id)
                config.elementsData = arr
                gra.removeGraphic(ELE)
            }
            const data = removeTreeByKey(TreeData, e.uuid)
            setTreeData(data)
            config.elements = data
            onSave()
        }

        const onSaveElement = (data) => {
            const { elementsData } = config
            const arr = elementsData.filter(v => v.id !== data.id)
            arr.push(data)
            config.elementsData = arr
            onSave()
        }

        const onSave = () => {
            MapEvent.emit({ type: 'onSaveConfig', data: config })
        }

        const items = (e) => (
            [
                { key: 'modify', label: (<Button type="link" icon={<EditOutlined />} onClick={() => onModify(e)} >修改数据</Button>) },
                e.fieldType === 'element' && {
                    key: 'delete',
                    label: (
                        <Popconfirm
                            title="删除提醒!"
                            description="是否要删除当前数据?"
                            onConfirm={() => onDelete(e)}
                            okText="删除"
                            cancelText="取消"
                        >
                            <Button type="link" danger icon={<DeleteOutlined />}>删除数据</Button>
                        </Popconfirm>
                    )
                },
            ]
        )

        useEffect(() => {
            if (gra) {
                gra.on(mars3d.EventType.editStart, (e) => {
                    message.loading({ key: 'element', duration: 0, content: '元素编辑中...' })
                    const data = e.graphic.options
                    data.type = e.editType
                    if (singlePoint.includes(e.editType)) data.position = e.graphic.coordinate
                    else if (singlePoints.includes(e.editType)) data.position = e.graphic.coordinates
                    else data.positions = e.graphic.coordinates
                    setActivate(data)
                    setOpen(true)
                })
                gra.on(mars3d.EventType.editStop, (e) => {
                    // console.log('e', e)
                    message.success({ key: 'element', content: '完成元素编辑!' })
                    const data = e.graphic.options
                    if (singlePoint.includes(e.editType)) data.position = e.graphic.coordinate
                    else if (singlePoints.includes(e.editType)) data.position = e.graphic.coordinates
                    else data.positions = e.graphic.coordinates
                    onSaveElement(data)
                    setOpen(false)
                    gra.stopDraw()
                })
                gra.on(mars3d.EventType.editMovePoint, (e) => {
                    if (singlePoint.includes(e.editType)) setActivate({ ...e.graphic.options, position: e.graphic.coordinate })
                })
            }
            return () => { gra.isAutoEditing = false }
        }, [gra])

        const onDetection = (data) => {
            const { id, type } = Activate
            const ELE = gra.getGraphicById(id)
            const { coordinate } = ELE
            if (data.lng) {
                const position = coordinate
                position[0] = data.lng
                ELE.setOptions({ position })
            }
            else if (data.lat) {
                const position = coordinate
                position[1] = data.lat
                ELE.setOptions({ position })
            }
            else if (data.alt) {
                const position = coordinate
                position[2] = data.alt
                ELE.setOptions({ position })
            }
            else if (type === 'div') {
                const style = { ...Activate.style, ...data.style }
                style.html = initStartDraw.DivTemplate[style.temp]({ style })
                ELE.setOptions({ style })
            }
            else ELE.setOptions(data)

        }

        const CallBackFuncTwo = (e) => {
            const { type, data } = e
            const MapReturn = new Map([
                ['onDetection', () => onDetection(data)],
            ])
            const func = MapReturn.get(type)
            return func && func()
        }
        const FORMEVENT = useEventEmitter()
        FORMEVENT.useSubscription(CallBackFuncTwo)

        const onSwitchStatus = (e, status) => {
            updateTreeByKey(config.elementsData, e.id, status, 'id', 'show')
            e.setOptions({ show: status })
            setTreeData([...TreeData])
        }

        return (
            <div className="SetMars3dMap SetMars3dMapA04">
                <div className="TreeList">
                    <Tree
                        draggable
                        blockNode
                        onDrop={e => {
                            const data = onTreeDrop(e, TreeData, 'uuid')
                            config.elements = data
                            setTreeData(data)
                            onSave()
                        }}
                        selectable={false}
                        treeData={TreeData}
                        defaultExpandAll
                        fieldNames={{ key: 'uuid' }}
                        titleRender={e => {
                            const { uuid, fieldName, fieldType, elementType } = e
                            const element = MappingData.mars3d__elementType.find(v => v.value === elementType)
                            const ELE = gra.getGraphicById(uuid)

                            return (
                                <div className="TreeList__item">
                                    <div className="TreeItem__title">
                                        <div>{fieldType === 'group' ? '分组' : element?.label}</div>
                                        <div>{fieldName}</div>
                                    </div>
                                    <div className="TreeItem__options">
                                        {fieldType !== 'group' &&
                                            <>
                                                {ELE ?
                                                    <>
                                                        <Tooltip title="元素定位">
                                                            <EnvironmentOutlined onClick={() => onLocate(e)} />
                                                        </Tooltip>
                                                        {ELE.show ?
                                                            <Tooltip title="当前 : 显示">
                                                                <EyeOutlined onClick={() => onSwitchStatus(ELE, false)} />
                                                            </Tooltip> :
                                                            <Tooltip title="当前 : 隐藏">
                                                                <EyeInvisibleOutlined onClick={() => onSwitchStatus(ELE, true)} />
                                                            </Tooltip>
                                                        }
                                                    </> :
                                                    <Tooltip title="绘制元素">
                                                        <NodeIndexOutlined onClick={() => onDraw(e)} />
                                                    </Tooltip>
                                                }
                                            </>
                                        }
                                        <Dropdown menu={{ items: items(e) }} trigger={['click']}>
                                            <Button type='link' onClick={e => e.preventDefault()}>更多<DownOutlined /></Button>
                                        </Dropdown>
                                    </div>
                                </div>
                            )
                        }}
                    />
                </div>
                <div className="Button">
                    <Button type="primary" size="large" icon={<BuildOutlined />} onClick={onAdd} loading={loading}>新增元素</Button>
                </div>
                <Drawer
                    title="编辑元素"
                    placement='left'
                    closable={false}
                    open={Open}
                    mask={false}
                    destroyOnHidden
                >
                    <div className="SetMars3dMapA04__Drawer">
                        <FormTempMapping formItem={Marsd3dConfig[Activate.type]} FORMEVENT={FORMEVENT} Initial={Activate} NotSubmit detection />
                    </div>
                </Drawer>
            </div>
        )
    }



    return <div>SetMars3dMap - 未知组件</div>
};

export default SetMars3dMap;